package com.slz3.business.module.goodsManagement.gooGoods.sync;

import com.slz3.business.frame.module.DomainEntity;
import com.slz3.business.frame.module.Repositorys;
import com.slz3.business.frame.redis.RK;
import com.slz3.business.frame.util.VE;
import com.slz3.business.module.goodsManagement.gooGoods.domain.GooGoods;
import com.slz3.business.module.goodsManagement.gooGoods.domain.GooGoodsEntity;
import com.slz3.business.module.goodsManagement.gooGoods.enums.GooGoodsShelvesFlag;
import com.slz3.business.module.goodsManagement.gooGoods.enums.GooGoodsTypeEnum;
import com.slz3.business.module.goodsManagement.gooGoods.enums.GoodsIsactiveEnum;
import com.slz3.business.module.goodsManagement.gooTypeLevel1.domain.GooTypeLevel1;
import org.springframework.data.redis.core.RedisTemplate;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import static java.util.stream.Collectors.toList;

public class GooGoodsPGToRedisSync {

    public static void sync(RedisTemplate redisTemplate, List<DomainEntity> validAll) {
        // 强转 | 过滤已下架
        List<GooGoods> goodsList = validAll.stream()
                .map(item -> (GooGoods) item)
                .filter(item -> GooGoodsShelvesFlag.isNo(item.getSerShelfState()))
                .collect(toList());

        // null stock
        // null last modify time
        goodsList.forEach(item -> {
            item.setSerGoodsPricel(item.getSerGoodsPricel() == null ? BigDecimal.ZERO : item.getSerGoodsPricel());
            item.setSerGoodsJifenNum(item.getSerGoodsJifenNum() == null ? 0 : item.getSerGoodsJifenNum());
            item.setSerGoodsStock(item.getSerGoodsStock() == null ? 0 : item.getSerGoodsStock());
            item.setLastModifyTime(item.getLastModifyTime() == null ? item.getCreateTime() : item.getLastModifyTime());
        });

        // 商品 - 一级分类
        Map<UUID, GooTypeLevel1> gooTypeLevel1Map = Repositorys.gooTypeLevel1.findAllMapByUuid();

        /** 首页排序 **/
        syncIndexDefault(redisTemplate, goodsList);

        /** 排序（积分 | 现金）默认 **/
        syncGoodsTypeCashOrPointDefault(redisTemplate, goodsList);
        /** 排序（积分 | 现金）新品 **/
        syncGoodsTypeCashOrPointNew(redisTemplate, goodsList);
        /** 排序（积分 | 现金）销量 **/
        syncGoodsTypeCashOrPointSales(redisTemplate, goodsList);
        /** 排序（积分 | 现金）金额 **/
        syncGoodsTypeCashOrPointPrice(redisTemplate, goodsList);

        /** 排序（积分 | 现金）（分类）默认 **/
        syncGoodsTypeCashOrPointClassifyDefault(redisTemplate, goodsList, gooTypeLevel1Map);
        /** 排序（积分 | 现金）（分类）新品 **/
        syncGoodsTypeCashOrPointClassifyNew(redisTemplate, goodsList, gooTypeLevel1Map);
        /** 排序（积分 | 现金）（分类）销量 **/
        syncGoodsTypeCashOrPointClassifySales(redisTemplate, goodsList, gooTypeLevel1Map);
        /** 排序（积分 | 现金）（分类）金额 **/
        syncGoodsTypeCashOrPointClassifyPrice(redisTemplate, goodsList, gooTypeLevel1Map);
    }

    private static void syncIndexDefault(RedisTemplate redisTemplate, List<GooGoods> goodsList) {
        String redisKey = RK.CONFIG_DOMIN__$DOMAIN$__UUID_LIST.replace("${Domain}", GooGoods.class.getSimpleName());
        redisTemplate.delete(redisKey);
        List<UUID> goodsListIndexHasStock = goodsList.stream()
                .filter(item -> item.getSerGoodsStock() > 0)
                .sorted(Comparator.comparing(GooGoods::getLastModifyTime).reversed())
                .map(GooGoods::getUuid)
                .collect(toList());
        List<UUID> goodsListIndexNotStock = goodsList.stream()
                .filter(item -> item.getSerGoodsStock() == 0)
                .map(GooGoods::getUuid)
                .collect(toList());
        if (VE.isNotEmpty(goodsListIndexHasStock))
            redisTemplate.opsForList().rightPushAll(redisKey, goodsListIndexHasStock);
        if (VE.isNotEmpty(goodsListIndexNotStock))
            redisTemplate.opsForList().rightPushAll(redisKey, goodsListIndexNotStock);
    }

    private static void syncGoodsTypeCashOrPointClassifyPrice(RedisTemplate redisTemplate, List<GooGoods> goodsList, Map<UUID, GooTypeLevel1> gooTypeLevel1Map) {
        gooTypeLevel1Map.values().stream().forEach(fieldMap -> {
            String cashSortKey = RK.CONFIG_DOMIN__GOO_GOODS__$GOODS_TYPE$__$TYPE_LEVEL1$__PRICE__UUID_LIST.replace("${GoodsType}", GooGoodsTypeEnum.CASH.name()).replace("${TypeLevel1}", fieldMap.getSerNum() == null ? "" : fieldMap.getSerNum());
            String pointSortKey = RK.CONFIG_DOMIN__GOO_GOODS__$GOODS_TYPE$__$TYPE_LEVEL1$__PRICE__UUID_LIST.replace("${GoodsType}", GooGoodsTypeEnum.POINTS.name()).replace("${TypeLevel1}", fieldMap.getSerNum() == null ? "" : fieldMap.getSerNum());
            redisTemplate.delete(cashSortKey);
            redisTemplate.delete(pointSortKey);
            List<UUID> goodsListSubCash = goodsList.stream()
                    .filter(item -> GoodsIsactiveEnum.isCash(item.getSerGoodsIsactive()))
                    .filter(item -> item.getSerGoodsT1() != null && item.getSerGoodsT1().equals(fieldMap.getUuid()))
                    .sorted(Comparator.comparing(GooGoods::getSerGoodsPricel))
                    .map(GooGoods::getUuid).collect(toList());
            if (VE.isNotEmpty(goodsListSubCash))
                redisTemplate.opsForList().rightPushAll(cashSortKey, goodsListSubCash);
            List<UUID> goodsListSubPoint = goodsList.stream()
                    .filter(item -> GoodsIsactiveEnum.isPoints(item.getSerGoodsIsactive()))
                    .filter(item -> item.getSerGoodsT1() != null && item.getSerGoodsT1().equals(fieldMap.getUuid()))
                    .sorted(Comparator.comparing(GooGoods::getSerGoodsJifenNum))
                    .map(GooGoods::getUuid).collect(toList());
            if (VE.isNotEmpty(goodsListSubPoint))
                redisTemplate.opsForList().rightPushAll(pointSortKey, goodsListSubPoint);
        });
    }

    private static void syncGoodsTypeCashOrPointClassifySales(RedisTemplate redisTemplate, List<GooGoods> goodsList, Map<UUID, GooTypeLevel1> gooTypeLevel1Map) {
        gooTypeLevel1Map.values().stream().forEach(fieldMap -> {
            String cashSortKey = RK.CONFIG_DOMIN__GOO_GOODS__$GOODS_TYPE$__$TYPE_LEVEL1$__SALES__UUID_LIST.replace("${GoodsType}", GooGoodsTypeEnum.CASH.name()).replace("${TypeLevel1}", fieldMap.getSerNum() == null ? "" : fieldMap.getSerNum());
            String pointSortKey = RK.CONFIG_DOMIN__GOO_GOODS__$GOODS_TYPE$__$TYPE_LEVEL1$__SALES__UUID_LIST.replace("${GoodsType}", GooGoodsTypeEnum.POINTS.name()).replace("${TypeLevel1}", fieldMap.getSerNum() == null ? "" : fieldMap.getSerNum());
            redisTemplate.delete(cashSortKey);
            redisTemplate.delete(pointSortKey);
            List<UUID> goodsListSubCash = goodsList.stream()
                    .filter(item -> GoodsIsactiveEnum.isCash(item.getSerGoodsIsactive()))
                    .filter(item -> item.getSerGoodsT1() != null && item.getSerGoodsT1().equals(fieldMap.getUuid()))
                    .sorted(Comparator.comparingInt(GooGoods::getSerGoodsStock).reversed())
//                    .sorted(Comparator.comparing(GooGoods::getCreateTime))
                    .map(GooGoods::getUuid).collect(toList());
            if (VE.isNotEmpty(goodsListSubCash))
                redisTemplate.opsForList().rightPushAll(cashSortKey, goodsListSubCash);
            List<UUID> goodsListSubPoint = goodsList.stream()
                    .filter(item -> GoodsIsactiveEnum.isPoints(item.getSerGoodsIsactive()))
                    .filter(item -> item.getSerGoodsT1() != null && item.getSerGoodsT1().equals(fieldMap.getUuid()))
                    .sorted(Comparator.comparingInt(GooGoods::getSerGoodsStock).reversed())
//                    .sorted(Comparator.comparing(GooGoods::getCreateTime))
                    .map(GooGoods::getUuid).collect(toList());
            if (VE.isNotEmpty(goodsListSubPoint))
                redisTemplate.opsForList().rightPushAll(pointSortKey, goodsListSubPoint);
        });
    }

    private static void syncGoodsTypeCashOrPointClassifyNew(RedisTemplate redisTemplate, List<GooGoods> goodsList, Map<UUID, GooTypeLevel1> gooTypeLevel1Map) {
        gooTypeLevel1Map.values().stream().forEach(fieldMap -> {
            String cashSortKey = RK.CONFIG_DOMIN__GOO_GOODS__$GOODS_TYPE$__$TYPE_LEVEL1$__NEW__UUID_LIST.replace("${GoodsType}", GooGoodsTypeEnum.CASH.name()).replace("${TypeLevel1}", fieldMap.getSerNum() == null ? "" : fieldMap.getSerNum());
            String pointSortKey = RK.CONFIG_DOMIN__GOO_GOODS__$GOODS_TYPE$__$TYPE_LEVEL1$__NEW__UUID_LIST.replace("${GoodsType}", GooGoodsTypeEnum.POINTS.name()).replace("${TypeLevel1}", fieldMap.getSerNum() == null ? "" : fieldMap.getSerNum());
            redisTemplate.delete(cashSortKey);
            redisTemplate.delete(pointSortKey);

            List<GooGoods> goodsListSubCash = goodsList.stream()
                    .filter(item -> GoodsIsactiveEnum.isCash(item.getSerGoodsIsactive()))
                    .filter(item -> item.getSerGoodsT1() != null && item.getSerGoodsT1().equals(fieldMap.getUuid()))
                    .collect(toList());
            List<UUID> goodsUuidListSubCashHasStock = goodsListSubCash.stream()
                    .filter(item -> item.getSerGoodsStock() > 0)
                    .sorted(Comparator.comparing(GooGoods::getLastModifyTime))
                    .map(GooGoods::getUuid)
                    .collect(toList());
            List<UUID> goodsUuidListSubCashNotStock = goodsListSubCash.stream()
                    .filter(item -> item.getSerGoodsStock() == 0)
                    .map(GooGoods::getUuid)
                    .collect(toList());
            if (VE.isNotEmpty(goodsUuidListSubCashHasStock))
                redisTemplate.opsForList().rightPushAll(cashSortKey, goodsUuidListSubCashHasStock);
            if (VE.isNotEmpty(goodsUuidListSubCashNotStock))
                redisTemplate.opsForList().rightPushAll(cashSortKey, goodsUuidListSubCashNotStock);

            List<GooGoods> goodsListSubPoint = goodsList.stream()
                    .filter(item -> GoodsIsactiveEnum.isPoints(item.getSerGoodsIsactive()))
                    .filter(item -> item.getSerGoodsT1() != null && item.getSerGoodsT1().equals(fieldMap.getUuid()))
                    .collect(toList());
            List<UUID> goodsUuidListSubPointHasStock = goodsListSubPoint.stream()
                    .filter(item -> item.getSerGoodsStock() > 0)
                    .sorted(Comparator.comparing(GooGoods::getLastModifyTime))
                    .map(GooGoods::getUuid)
                    .collect(toList());
            List<UUID> goodsUuidListSubPointNotStock = goodsListSubPoint.stream()
                    .filter(item -> item.getSerGoodsStock() == 0)
                    .map(GooGoods::getUuid)
                    .collect(toList());
            if (VE.isNotEmpty(goodsUuidListSubPointHasStock))
                redisTemplate.opsForList().rightPushAll(cashSortKey, goodsUuidListSubPointHasStock);
            if (VE.isNotEmpty(goodsUuidListSubPointNotStock))
                redisTemplate.opsForList().rightPushAll(cashSortKey, goodsUuidListSubPointNotStock);
        });
    }

    private static void syncGoodsTypeCashOrPointClassifyDefault(RedisTemplate redisTemplate, List<GooGoods> goodsList, Map<UUID, GooTypeLevel1> gooTypeLevel1Map) {
        gooTypeLevel1Map.values().stream().forEach(fieldMap -> {
            String cashSortKey = RK.CONFIG_DOMIN__GOO_GOODS__$GOODS_TYPE$__$TYPE_LEVEL1$__UUID_LIST.replace("${GoodsType}", GooGoodsTypeEnum.CASH.name()).replace("${TypeLevel1}", fieldMap.getSerNum() == null ? "" : fieldMap.getSerNum());
            String pointSortKey = RK.CONFIG_DOMIN__GOO_GOODS__$GOODS_TYPE$__$TYPE_LEVEL1$__UUID_LIST.replace("${GoodsType}", GooGoodsTypeEnum.POINTS.name()).replace("${TypeLevel1}", fieldMap.getSerNum() == null ? "" : fieldMap.getSerNum());
            redisTemplate.delete(cashSortKey);
            redisTemplate.delete(pointSortKey);
            List<UUID> goodsListSubCash = goodsList.stream()
                    .filter(item -> GoodsIsactiveEnum.isCash(item.getSerGoodsIsactive()))
                    .filter(item -> item.getSerGoodsT1() != null && item.getSerGoodsT1().equals(fieldMap.getUuid()))
                    .sorted(Comparator.comparingInt(GooGoods::getSerGoodsStock).reversed())
//                    .sorted(Comparator.comparing(GooGoods::getCreateTime).reversed())
                    .map(GooGoods::getUuid).collect(toList());
            if (VE.isNotEmpty(goodsListSubCash))
                redisTemplate.opsForList().rightPushAll(cashSortKey, goodsListSubCash);
            List<UUID> goodsListSubPoint = goodsList.stream()
                    .filter(item -> GoodsIsactiveEnum.isPoints(item.getSerGoodsIsactive()))
                    .filter(item -> item.getSerGoodsT1() != null && item.getSerGoodsT1().equals(fieldMap.getUuid()))
                    .sorted(Comparator.comparingInt(GooGoods::getSerGoodsStock).reversed())
//                    .sorted(Comparator.comparing(GooGoods::getCreateTime).reversed())
                    .map(GooGoods::getUuid).collect(toList());
            if (VE.isNotEmpty(goodsListSubPoint))
                redisTemplate.opsForList().rightPushAll(pointSortKey, goodsListSubPoint);
        });
    }

    private static void syncGoodsTypeCashOrPointPrice(RedisTemplate redisTemplate, List<GooGoods> goodsList) {
        String cashSortKey = RK.CONFIG_DOMIN__GOO_GOODS__$GOODS_TYPE$__PRICE__UUID_LIST.replace("${GoodsType}", GooGoodsTypeEnum.CASH.name());
        String pointSortKey = RK.CONFIG_DOMIN__GOO_GOODS__$GOODS_TYPE$__PRICE__UUID_LIST.replace("${GoodsType}", GooGoodsTypeEnum.POINTS.name());
        redisTemplate.delete(cashSortKey);
        redisTemplate.delete(pointSortKey);

        List<UUID> goodsListSubCash = goodsList.stream()
                .filter(item -> GoodsIsactiveEnum.isCash(item.getSerGoodsIsactive()))
                .sorted(Comparator.comparing(GooGoods::getSerGoodsPricel)) // 商品价格
                .map(GooGoods::getUuid).collect(toList());
        if (VE.isNotEmpty(goodsListSubCash))
            redisTemplate.opsForList().rightPushAll(cashSortKey, goodsListSubCash);

        List<UUID> goodsListSubPoint = goodsList.stream()
                .filter(item -> GoodsIsactiveEnum.isPoints(item.getSerGoodsIsactive()))
                .sorted(Comparator.comparing(GooGoods::getSerGoodsJifenNum)) // 所需积分
                .map(GooGoods::getUuid).collect(toList());
        if (VE.isNotEmpty(goodsListSubPoint))
            redisTemplate.opsForList().rightPushAll(pointSortKey, goodsListSubPoint);
    }

    private static void syncGoodsTypeCashOrPointSales(RedisTemplate redisTemplate, List<GooGoods> goodsList) {
        String cashSortKey = RK.CONFIG_DOMIN__GOO_GOODS__$GOODS_TYPE$__SALES__UUID_LIST.replace("${GoodsType}", GooGoodsTypeEnum.CASH.name());
        String pointSortKey = RK.CONFIG_DOMIN__GOO_GOODS__$GOODS_TYPE$__SALES__UUID_LIST.replace("${GoodsType}", GooGoodsTypeEnum.POINTS.name());
        redisTemplate.delete(cashSortKey);
        redisTemplate.delete(pointSortKey);
        List<UUID> goodsListSubCash = goodsList.stream()
                .filter(item -> GoodsIsactiveEnum.isCash(item.getSerGoodsIsactive()))
                .sorted(Comparator.comparingInt(GooGoods::getSerGoodsStock).reversed())
//                .sorted(Comparator.comparing(GooGoods::getCreateTime))
                .map(GooGoods::getUuid).collect(toList());
        if (VE.isNotEmpty(goodsListSubCash))
            redisTemplate.opsForList().rightPushAll(cashSortKey, goodsListSubCash);
        List<UUID> goodsListSubPoint = goodsList.stream()
                .filter(item -> GoodsIsactiveEnum.isPoints(item.getSerGoodsIsactive()))
                .sorted(Comparator.comparingInt(GooGoods::getSerGoodsStock).reversed())
//                .sorted(Comparator.comparing(GooGoods::getCreateTime))
                .map(GooGoods::getUuid).collect(toList());
        if (VE.isNotEmpty(goodsListSubPoint))
            redisTemplate.opsForList().rightPushAll(pointSortKey, goodsListSubPoint);
    }

    private static void syncGoodsTypeCashOrPointNew(RedisTemplate redisTemplate, List<GooGoods> goodsList) {
        String cashSortKey = RK.CONFIG_DOMIN__GOO_GOODS__$GOODS_TYPE$__NEW__UUID_LIST.replace("${GoodsType}", GooGoodsTypeEnum.CASH.name());
        String pointSortKey = RK.CONFIG_DOMIN__GOO_GOODS__$GOODS_TYPE$__NEW__UUID_LIST.replace("${GoodsType}", GooGoodsTypeEnum.POINTS.name());
        redisTemplate.delete(cashSortKey);
        redisTemplate.delete(pointSortKey);
        List<GooGoods> goodsListSubCash = goodsList.stream()
                .filter(item -> GoodsIsactiveEnum.isCash(item.getSerGoodsIsactive()))
                .collect(toList());
        List<UUID> goodsUuidListSubCashHasStock = goodsListSubCash.stream()
                .filter(item -> item.getSerGoodsStock() > 0)
                .sorted(Comparator.comparing(GooGoods::getLastModifyTime))
                .map(GooGoods::getUuid)
                .collect(toList());
        List<UUID> goodsUuidListSubCashNotStock = goodsListSubCash.stream()
                .filter(item -> item.getSerGoodsStock() == 0)
                .map(GooGoods::getUuid)
                .collect(toList());
        if (VE.isNotEmpty(goodsUuidListSubCashHasStock))
            redisTemplate.opsForList().rightPushAll(cashSortKey, goodsUuidListSubCashHasStock);
        if (VE.isNotEmpty(goodsUuidListSubCashNotStock))
            redisTemplate.opsForList().rightPushAll(cashSortKey, goodsUuidListSubCashNotStock);

        List<GooGoods> goodsListSubPoint = goodsList.stream()
                .filter(item -> GoodsIsactiveEnum.isPoints(item.getSerGoodsIsactive()))
                .collect(toList());
        List<UUID> goodsUuidListSubPointHasStock = goodsListSubPoint.stream()
                .filter(item -> item.getSerGoodsStock() > 0)
                .sorted(Comparator.comparing(GooGoods::getLastModifyTime))
                .map(GooGoods::getUuid)
                .collect(toList());
        List<UUID> goodsUuidListSubPointNotStock = goodsListSubPoint.stream()
                .filter(item -> item.getSerGoodsStock() == 0)
                .map(GooGoods::getUuid)
                .collect(toList());
        if (VE.isNotEmpty(goodsUuidListSubPointHasStock))
            redisTemplate.opsForList().rightPushAll(pointSortKey, goodsUuidListSubPointHasStock);
        if (VE.isNotEmpty(goodsUuidListSubPointNotStock))
            redisTemplate.opsForList().rightPushAll(pointSortKey, goodsUuidListSubPointNotStock);
    }

    private static void syncGoodsTypeCashOrPointDefault(RedisTemplate redisTemplate, List<GooGoods> goodsList) {
        String cashSortKey = RK.CONFIG_DOMIN__GOO_GOODS__$GOODS_TYPE$__UUID_LIST.replace("${GoodsType}", GooGoodsTypeEnum.CASH.name());
        String pointSortKey = RK.CONFIG_DOMIN__GOO_GOODS__$GOODS_TYPE$__UUID_LIST.replace("${GoodsType}", GooGoodsTypeEnum.POINTS.name());
        redisTemplate.delete(cashSortKey);
        redisTemplate.delete(pointSortKey);
        List<UUID> goodsListSubCash = goodsList.stream()
                .filter(item -> GoodsIsactiveEnum.isCash(item.getSerGoodsIsactive()))
                .sorted(Comparator.comparing(GooGoodsEntity::getSerGoodsStock).reversed())
//                .sorted(Comparator.comparing(GooGoods::getCreateTime).reversed())
                .map(GooGoods::getUuid).collect(toList());
        if (VE.isNotEmpty(goodsListSubCash))
            redisTemplate.opsForList().rightPushAll(cashSortKey, goodsListSubCash);
        List<UUID> goodsListSubPoint = goodsList.stream()
                .filter(item -> GoodsIsactiveEnum.isPoints(item.getSerGoodsIsactive()))
                .sorted(Comparator.comparing(GooGoods::getSerGoodsStock).reversed())
//                .sorted(Comparator.comparing(GooGoods::getCreateTime).reversed())
                .map(GooGoods::getUuid).collect(toList());
        if (VE.isNotEmpty(goodsListSubPoint))
            redisTemplate.opsForList().rightPushAll(pointSortKey, goodsListSubPoint);
    }

}
